/*
 * QuerySPCFrame.java
 *
 * Created on Dec 15, 2011, 11:08:59 PM
 */
package gui;

/**
 *
 * @author suzann
 */

/*
 * Import Java Classes
 */

import chart.QuerySPCChartPanel;
import db.DatabaseManager;
import db.entity.PadLife;
import db.entity.PadeLapse;
import db.entity.TaperMap;
import excelexporter.ExcelExporter;
import excelexporter.QuerySPCBean;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.DefaultFontMapper;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

import util.ErrorMessage;
import util.PropertiesLoader;
import util.SimpleFileFilter;

public class QuerySPCFrame extends javax.swing.JFrame {
    /** Creates new form QuerySPCFrame */
    public QuerySPCFrame() {
        initComponents();
        //Variables initialisation
        dm = new db.DatabaseManager();
        cbModel = new DefaultComboBoxModel();
        spcPnl = new QuerySPCChartPanel();
        populateStations();
        setInitData();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jcbStation = new javax.swing.JComboBox();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jbtDisplay = new javax.swing.JButton();
        jbtExcel = new javax.swing.JButton();
        jdcFromDate = new com.toedter.calendar.JDateChooser();
        jdcToDate = new com.toedter.calendar.JDateChooser();
        dateFrom = new Date();
        sdmFrom = new SpinnerDateModel(dateFrom, null, null, 11);
        jspFromTime = new javax.swing.JSpinner(sdmFrom);
        dateTo = new Date();
        sdmTo = new SpinnerDateModel(dateTo, null, null, 11);
        jspToTime = new javax.swing.JSpinner(sdmTo);
        jbtPDF = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setFocusable(false);
        setMinimumSize(new java.awt.Dimension(1024, 688));

        jLabel1.setText("Station");

        jLabel2.setText("From");

        jLabel3.setText("To");

        jbtDisplay.setText("Display");
        jbtDisplay.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtDisplayActionPerformed(evt);
            }
        });

        jbtExcel.setText("Export to Excel");
        jbtExcel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtExcelActionPerformed(evt);
            }
        });

        deFrom = new JSpinner.DateEditor(jspFromTime, "hh:mm a");
        jspFromTime.setEditor(deFrom);

        deTo = new JSpinner.DateEditor(jspToTime, "hh:mm a");
        jspToTime.setEditor(deTo);

        jbtPDF.setText("Export to PDF");
        jbtPDF.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtPDFActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(18, 18, 18)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel3)))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabel1)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jcbStation, 0, 225, Short.MAX_VALUE)
                    .addComponent(jdcToDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jdcFromDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jspToTime, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jbtDisplay)
                        .addGap(10, 10, 10)
                        .addComponent(jbtExcel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jbtPDF))
                    .addComponent(jspFromTime, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(265, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jcbStation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jspFromTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jdcFromDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jspToTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jbtDisplay)
                                .addComponent(jbtExcel)
                                .addComponent(jbtPDF))
                            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jdcToDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel3)))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        getContentPane().add(jPanel1, java.awt.BorderLayout.PAGE_END);

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-984)/2, (screenSize.height-578)/2, 984, 578);
    }// </editor-fold>

    /****************************************************************************
     * Action Listeners
     ****************************************************************************/
    private void jbtDisplayActionPerformed(java.awt.event.ActionEvent evt) {                                           
        showQuerySPCChart();
    }                                          

    private void jbtExcelActionPerformed(java.awt.event.ActionEvent evt) {                                         
        exportToExcel();
    }                                        

    private void jbtPDFActionPerformed(java.awt.event.ActionEvent evt) {
        exportToPDF();
    }

    /****************************************************************************
     * Internal Operations
     ****************************************************************************/
    /**
     * This method sets the initial data for Tend Chart Display at first launch.
     * @param 
     */
    private void setInitData()
    {
        Calendar today = Calendar.getInstance();
        
        Calendar yesterday = Calendar.getInstance();
        yesterday.setTimeInMillis(today.getTimeInMillis() - 86400000L);
        
        this.jdcToDate.setDate(today.getTime());
        this.jdcFromDate.setDate(yesterday.getTime());
        
        jcbStation.setSelectedIndex(-1);
    }
    
    /**
     * This method populates the combo box for stations
     * @param 
     */
    private void populateStations()
    {
        List<TaperMap> lstStations = dm.listTaperMap();
        List <String> stringStations = new ArrayList<String>();
        
        for(int i = 0; i<lstStations.size(); i++)
        {
            stringStations.add(lstStations.get(i).getStationName());
        }
        
        Collections.sort(stringStations);
        for(int i = 0; i<stringStations.size(); i++)
        {
            cbModel.addElement(stringStations.get(i));
        }
        jcbStation.setModel(cbModel);
    }
    
    /**
     * This method get component values and show the Query SPC Chart.
     * @param 
     */    
    protected void showQuerySPCChart()
    {
    	if(! validateInput())
    		return ;
    	
        /*get the inputs*/
        //1. Get the station string
        int selectedIndex = jcbStation.getSelectedIndex();
        String station = jcbStation.getItemAt(selectedIndex).toString();
        
        //2. From DateTime
        Calendar fromTime = Calendar.getInstance();
        fromTime.setTime(sdmFrom.getDate());
        Calendar fromDateTime = Calendar.getInstance();
        fromDateTime.setTime(jdcFromDate.getDate());        
        fromDateTime.set(11, fromTime.get(11));
        fromDateTime.set(12, fromTime.get(12));
        fromDateTime.set(13, fromTime.get(13));
        Date startDate = fromDateTime.getTime();
        System.out.println("From date =" + fromDateTime.getTime());
        
        //3. To DateTime
        Calendar toTime = Calendar.getInstance();
        toTime.setTime(sdmTo.getDate());
        Calendar toDateTime = Calendar.getInstance();
        toDateTime.setTime(jdcToDate.getDate());
        toDateTime.set(11, toTime.get(11));
        toDateTime.set(12, toTime.get(12));
        toDateTime.set(13, toTime.get(13));
        Date endDate = toDateTime.getTime();
        System.out.println("to date =" + toDateTime.getTime());
        
        sList = dm.listPadlifeByStationNameDate(station, startDate, endDate);
        spcPnl.loadData(sList);
        
        //place the chart.
        spcPnl.setVisible(true);
        this.getContentPane().add(spcPnl,java.awt.BorderLayout.CENTER);
        this.invalidate();
        this.validate();
    }
    
    private boolean validateInput()
    {    	
    	// VALIDATE STATION NUMBER
    	if(jcbStation.getSelectedItem() == null)
    	{
    		String errMsg = "Please select a station number.";
    		ErrorMessage.displayError(ErrorMessage.WARNING_ERROR, false, "Validation Error", errMsg);
    		return false;
    	}
    	
    	// VALIDATE BLANK FIELDS
    	boolean blankField = false;
    	String blankField_str = "";
    	if(jdcFromDate.getDate()==null)
    	{
    		blankField_str += "jdcFromDate;";
    		blankField = true;
    	}    	
    	if(jdcToDate.getDate()==null)
    	{
    		blankField_str += "jdcToDate;";
    		blankField = true;
    	}    	
    	
    	if(blankField)
    	{
    		String errMsg = "Please fill in the following field: \n" + blankField_str;
    		ErrorMessage.displayError(ErrorMessage.WARNING_ERROR, false, "Validation Error", errMsg);
    		return false;
    	}
    	
    	// VALIDATE FROM DATE BEFORE TO DATE
    	Calendar fromTime = Calendar.getInstance();
        fromTime.setTime(sdmFrom.getDate());
        Calendar fromDateTime = Calendar.getInstance();
        fromDateTime.setTime(jdcFromDate.getDate());        
        fromDateTime.set(11, fromTime.get(11));
        fromDateTime.set(12, fromTime.get(12));
        fromDateTime.set(13, fromTime.get(13));
        Date startDate = fromDateTime.getTime();

        Calendar toTime = Calendar.getInstance();
        toTime.setTime(sdmTo.getDate());
        Calendar toDateTime = Calendar.getInstance();
        toDateTime.setTime(jdcToDate.getDate());
        toDateTime.set(11, toTime.get(11));
        toDateTime.set(12, toTime.get(12));
        toDateTime.set(13, toTime.get(13));
        Date endDate = toDateTime.getTime();
		
    	if(! startDate.before(endDate))
    	{
    		String errMsg = "From Date should be a date before To Date.";
    		ErrorMessage.displayError(ErrorMessage.WARNING_ERROR, false, "Validation Error", errMsg);
    		return false;
    	}
    	
    	// Difference between From Data and To Date should be within range in properties file
    	int difference = toDateTime.get(Calendar.DAY_OF_YEAR) - fromDateTime.get(Calendar.DAY_OF_YEAR);
    	
    	if (difference > PropertiesLoader.getQuerySPCMaxRange())
    	{
    		String errMsg = "To Date cannot be "+PropertiesLoader.getQuerySPCMaxRange()+" days after From Date.";
    		ErrorMessage.displayError(ErrorMessage.WARNING_ERROR, false, "Validation Error", errMsg);
    		return false;
    	}    	
    	
    	return true;
    }
    
    private void exportToExcel()
    {
    	if(!(validateInput()))
    		return ;
    	
        /*get the inputs*/
        //1. Get the station string
        int selectedIndex = jcbStation.getSelectedIndex();
        String station = jcbStation.getItemAt(selectedIndex).toString();
        
        //2. From DateTime
        Calendar fromTime = Calendar.getInstance();
        fromTime.setTime(sdmFrom.getDate());
        Calendar fromDateTime = Calendar.getInstance();
        fromDateTime.setTime(jdcFromDate.getDate());        
        fromDateTime.set(11, fromTime.get(11));
        fromDateTime.set(12, fromTime.get(12));
        fromDateTime.set(13, fromTime.get(13));
        Date startDate = fromDateTime.getTime();
        System.out.println("From date =" + fromDateTime.getTime());
        
        //3. To DateTime
        Calendar toTime = Calendar.getInstance();
        toTime.setTime(sdmTo.getDate());
        Calendar toDateTime = Calendar.getInstance();
        toDateTime.setTime(jdcToDate.getDate());
        toDateTime.set(11, toTime.get(11));
        toDateTime.set(12, toTime.get(12));
        toDateTime.set(13, toTime.get(13));
        Date endDate = toDateTime.getTime();
        System.out.println("to date =" + toDateTime.getTime());
        
        sList = dm.listPadlifeByStationNameDate(station, startDate, endDate);
        ArrayList<QuerySPCBean> beanLS = new ArrayList<QuerySPCBean>();
        
        for(Object padLife_obj : sList){
        	if(!(padLife_obj instanceof PadLife))
        		continue ;
        		
        	PadLife padLifeItem = (PadLife)padLife_obj;
			// Calculation to get the data to plot the graph
			String padID = padLifeItem.getId().getStartLife()+""+ padLifeItem.getId().getStationName();
			List<PadeLapse> peList = dm.listPadElapseOfPadID(padID);
			long elapse = 0L;
			
			for(PadeLapse peItem : peList)
				elapse += peItem.getElapseTimeMillis();
				
			QuerySPCBean bean = new QuerySPCBean();
			bean.setPadStartTme(padLifeItem.getId().getStartLife());
			bean.setStation(padLifeItem.getId().getStationName());
			bean.setTotalPadLife(""+(elapse/3600000.0D));
			
			beanLS.add(bean);
		}
        new ExcelExporter().generateSPCExcelData(beanLS);
    }
    
    private void exportToPDF() {
    	JFileChooser fc = new JFileChooser();
    	fc.setFileSelectionMode(0);
    	fc.setFileFilter(new SimpleFileFilter("pdf"));
    	
    	int returnVal = fc.showSaveDialog(this);
    	if (returnVal == 0) {
    		File file = fc.getSelectedFile();
    		
    		String path = file.getAbsolutePath();
    		
    		if (!path.endsWith(".pdf")) {
    		path = path + ".pdf";
    		}
    		
    		String finalPath = path;
    		try {
    			OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(finalPath)));
    			Rectangle pagesize = new Rectangle(842, 595);
    			Document document = new Document(pagesize, 50.0F, 50.0F, 50.0F, 50.0F);
    			try {
    				PdfWriter writer = PdfWriter.getInstance(document, out);
    				document.addAuthor("JFreeChart");
    				document.addSubject("Demonstration");
    				document.open();
    				PdfContentByte cb = writer.getDirectContent();
    				PdfTemplate tp = cb.createTemplate(842, 595);
    				Graphics2D g2 = tp.createGraphics(842, 595, new DefaultFontMapper());
    				Rectangle2D r2D = new Rectangle2D.Double(0.0D, 0.0D, 842, 595);

    				spcPnl.drawChart(g2, r2D);

    				g2.dispose();
    				cb.addTemplate(tp, 0.0F, 0.0F);
    			} catch (DocumentException de) {
    				System.err.println(de.getMessage());
    			}
    			document.close();
    			out.close();
    			JOptionPane.showMessageDialog(null, "Graph successfully exported to PDF.", "Export Successfully", JOptionPane.PLAIN_MESSAGE);
    		}
    		catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public void addNotify() {
        super.addNotify();
        // Buffer
        createBufferStrategy(2);           
        //BufferStrategy strategy = getBufferStrategy();
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(QuerySPCFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(QuerySPCFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(QuerySPCFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(QuerySPCFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new QuerySPCFrame().setVisible(true);
            }
        });
    }
    /****************************************************************************
     * INTERNAL OPERATIONS : THE FRAME
     ****************************************************************************/
    
    /**
     * Prompts up a confirmation dialog to confirm the exit action.
     * Upon confirmation, dispose the frame.
     */
    private void onExit()
    {
    	//remove the chart panel
        spcPnl.setVisible(false);
        this.invalidate();
        this.validate();
        
        //reset all the values to default
        setInitData();
        
        //dispose the frame
        this.dispose();
    }
    
    /**
     * This is a hack for user to click on the 'x' button on window
     */
    protected void processWindowEvent(WindowEvent we)
    {
            if(we.getID() == WindowEvent.WINDOW_CLOSING)
                    onExit();
    }
    /****************************************************************************
     *  THE VARIABLES
     ****************************************************************************/
    
    // Variables declaration - do not modify
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton jbtDisplay;
    private javax.swing.JButton jbtExcel;
    private javax.swing.JButton jbtPDF;
    private javax.swing.JComboBox jcbStation;
    private com.toedter.calendar.JDateChooser jdcFromDate;
    private com.toedter.calendar.JDateChooser jdcToDate;
    private javax.swing.JSpinner jspFromTime;
    Date dateFrom;
    SpinnerDateModel sdmFrom;
    JSpinner.DateEditor deFrom;
    private javax.swing.JSpinner jspToTime;
    Date dateTo;
    SpinnerDateModel sdmTo;
    JSpinner.DateEditor deTo;
    // End of variables declaration
    QuerySPCChartPanel spcPnl;
    private DatabaseManager dm;
    private DefaultComboBoxModel cbModel;
    List sList;
}
